﻿#pragma once

#include <google/protobuf/message.h>

namespace Serializer
{

using google::protobuf::Message;
using google::protobuf::Descriptor;
using google::protobuf::FieldDescriptor;
using google::protobuf::Reflection;

int GetMessageStructSize(const Descriptor *desc);
bool StructToProtoInternal(const uint8_t *&bytes, Message &msg);
bool ProtoToStructInternal(uint8_t *&bytes, const Message &msg, int start);

// @brief Convert struct to protobuf message.
template<typename STRUCT, typename PROTO>
bool StructToProto(const STRUCT &in, PROTO &out)
{
	int size = GetMessageStructSize(out.GetDescriptor());
	// The struct should match protobuf, and should pack 1.
	if (size != sizeof(STRUCT)) return false;
	auto bytes = (const uint8_t*)&in;
	return StructToProtoInternal(bytes, out);
}

// @brief Convert protobuf message to struct.
template<typename PROTO, typename STRUCT>
bool ProtoToStruct(const PROTO &in, STRUCT &out)
{
	int size = GetMessageStructSize(in.GetDescriptor());
	// The struct should match protobuf, and should pack 1.
	if (size != sizeof(STRUCT)) return false;
	auto bytes = (uint8_t*)&out;
	return ProtoToStructInternal(bytes, in, 0);
}

} // namespace Serializer

